<?php
class AOChat
{
	public $c_FromId = 0;
	public $c_FromName = "";
	public $c_MsgBegin = '<b><font color="blue">';
	public $c_MsgEnd = '</font></b>';
	public $c_Host =  "townwars.ru";//"aochat.townwars.ru";
	public $c_Port = "5190";

	private $m_Host;
	private $m_Port;
	private $m_FromId;
	private $m_FromName;
	private $m_MsgBegin;
	private $m_MsgEnd;

	private $m_bConnected;
	private $m_Socket;

	private $m_iErrorNum;
	private $m_sErrorMsg;

	private $m_Buffer;

	public function __construct($bAutoconnect = true)
	{
		/**/$this->setUTF8();

		$this->m_FromId = 0;
		//$h = system('uname -n 2>&1', $ret);
		if(isset($_SERVER['SERVER_NAME']) && (preg_match('/t.avangardonline.ru$/', $_SERVER['SERVER_NAME']) || preg_match('|/home/buscan|', $_ENV['HOME'])))
		{
			$this->m_Host = 'game.t.avangardonline.ru';
		}
		else
		{
			$this->m_Host = $this->c_Host;
		}
		$this->m_Port = $this->c_Port;

		$this->m_bConnected = false;
		$this->m_iErrorNum = 0;
		$this->m_sErrorMsg = "";

		$this->m_Buffer = "";

		$this->m_Socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);		
		if($this->m_Socket === false)
		{			
			$this->m_iErrorNum = @socket_last_error();
			$this->m_sErrorMsg = @socket_strerror($this->m_iErrorNum);
			return;
		}
		if(@socket_connect($this->m_Socket, $this->m_Host, $this->m_Port) === false)
		{
			$this->m_iErrorNum = @socket_last_error($m_Socket);
			$this->m_sErrorMsg = @socket_strerror($m_iErrorNum);
		}
		else
		{
			//@socket_set_nonblock($this->m_Socket);
			//stream_set_timeout($this->m_Socket, 2, 0);
			$this->m_bConnected = true;
		}
		/*$this->m_bConnected = false;*/
	}

	private function cleanInput()
	{
		$dummy = '';
		do
		{
			$dummy = @socket_read($this->m_Socket, 1024, PHP_BINARY_READ);
		}
		while ($dummy != '');
	}
	
	public function printError()
	{
		echo "ErrorNum: " . $this->m_iErrorNum . "\n";
		echo "ErrorMsg: " . $this->m_sErrorMsg . "\n";
 	}
		
	public function __destruct()
	{
		if($this->m_bConnected)
		{
			@socket_close($this->m_Socket);
			$this->m_bConnected = false;
		}
	}

	public function isConnected()
	{
		return $this->m_bConnected;
	}

	private	function setUTF8()
	{
		//$this->db->sql_query("set character_set_client='utf8'");
		//$this->db->sql_query("set character_set_results='utf8'");
		//$this->db->sql_query("set collation_connection='utf8_general_ci'");
		setlocale(LC_ALL, 'ru_RU.UTF-8');
	}

	private function appendUINT8($data)
	{
		$this->m_Buffer .= pack("C", ($data & 0xFF));

		return 1;
	}

	private function insertUINT8($data)
	{
		$this->m_Buffer = pack("C", ($data & 0xFF)) . $this->m_Buffer;

		return 1;
	}

	private function appendUINT16($data)
	{
		$this->m_Buffer .= pack("n", ($data & 0xFFFF));

		return 2;
	}

	private function insertUINT16($data)
	{
		$this->m_Buffer = pack("n", ($data & 0xFFFF)) . $this->m_Buffer;

		return 2;
	}

	private function appendUINT32($data)
	{
		$this->m_Buffer .= pack("N", ($data & 0xFFFFFFFF));

		return 4;
	}

	private function insertUINT32($data)
	{
		$this->m_Buffer = pack("N", ($data & 0xFFFFFFFF)) . $this->m_Buffer;

		return 4;
	}

	private function appendString($str)
	{
		$len = 0;
		$strLen = strlen($str);
		$len += $this->appendUINT16($strLen);
		$this->m_Buffer .= $str;

		return $len + $strLen;
	}

	private function getBufSize()
	{
		return count(preg_split("//", $this->m_Buffer, -1, PREG_SPLIT_NO_EMPTY));
	}

	public function sendMessage($personage_id, $sMessage)
	{
		$this->m_Buffer = "";
		$this->appendSendMessage(1, $personage_id, $sMessage);
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		//$this->cleanInput();
		//$ret = @socket_read($this->m_Socket, $this->getBufSize() + 100, PHP_BINARY_READ);

		return $this->m_Buffer;
	}
	
	public function sendRawMessage($sMessage, $channel_id = 3)
	{
		$this->m_Buffer = "";
		$this->appendSendMessage($channel_id, 0, $sMessage);
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		//$this->cleanInput();
		//$ret = @socket_read($this->m_Socket, $this->getBufSize() + 100, PHP_BINARY_READ);

		return $this->m_Buffer;
	}

	public function reloadInfo($personage_id)
	{
		$this->m_Buffer = "";
		$this->appendReloadInfo($personage_id);
		//$this->cleanInput();
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		//$ret = @socket_read($this->m_Socket, $this->getBufSize() + 100, PHP_BINARY_READ);
	}

	private function appendReloadInfo($personage_id)
	{
		$len = 0;
		$len += $this->appendUINT32($personage_id);
		$this->insertHeader(301, $len);
	}

	public function reloadChannels()
	{
		$this->m_Buffer = "";
		$this->appendReloadChannels();
		//$this->cleanInput();
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		//$ret = @socket_read($this->m_Socket, $this->getBufSize() + 100, PHP_BINARY_READ);
	}

	private function appendReloadChannels()
	{
		$len = 0;
		$this->insertHeader(302, $len);
	}

	public function setQuiet($personage_id, $timeout)
	{
		$this->m_Buffer = "";
		$this->appendSetQuiet($personage_id, $timeout);
		//$this->cleanInput();
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		//$ret = @socket_read($this->m_Socket, $this->getBufSize() + 100, PHP_BINARY_READ);
	}

	public function getOnline()
	{
		$this->m_Buffer = "";
		$len = 0;
		$this->insertHeader(50, $len);
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		$ret = $this->readZeroEnded();
		return $ret;
	}
	
	public function getChannelOnline($channel_id)
	{
		$this->m_Buffer = "";
		$len = 0;
		$len += $this->appendUINT16($channel_id);
		$this->insertHeader(52, $len);
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		$ret = $this->readZeroEnded();
		return $ret;
	}
	
	public function getUserOnline($personage_id)
	{
		$this->m_Buffer = "";
		$len = 0;
		$len += $this->appendUINT32($personage_id);
		$this->insertHeader(51, $len);
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		$ret = $this->readZeroEnded();
		return $ret;
	}
	
	public function getServerStatus()
	{
		$this->m_Buffer = "<server-status-request/>\0";
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		//$this->cleanInput();
		//$ret = @socket_read($this->m_Socket, $this->getBufSize() + 100, PHP_BINARY_READ);
		$this->readZeroEnded();

		return $this->m_Buffer;
	}

	private function readZeroEnded()
	{
		$this->m_Buffer = "";
		//echo(@socket_last_error());		
		//echo(@socket_strerror($this->m_iErrorNum));
		//return false;
		//while ($r = socket_read($this->m_Socket, 1024)) $this->m_Buffer .= $r;
		//socket_recv($this->m_Socket, $char, 1, 0);
		//echo($char);
		//return false;
		while(true)
		{
			//echo(@socket_last_error());		
			//$char = socket_recv($this->m_Socket, $char, 1, 0);
			//echo(@socket_last_error());		
			$char = socket_read($this->m_Socket, 1, PHP_BINARY_READ);
			//echo "c=$char ";
			if(ord($char) <= 0)
			{
				//echo "break;";
				break;
			}
			//echo "+ ";
			$this->m_Buffer .= $char;
		}
		
		return $this->m_Buffer;
	}

	public function getUserOnlineStatus($personage_id)
	{
		$this->m_Buffer = "";
		$this->appendReqUserOnline($personage_id);		
		@socket_write($this->m_Socket, $this->m_Buffer, $this->getBufSize());
		$this->readZeroEnded();

		return $this->m_Buffer;
	}
	
	private function appendReqUserOnline($personage_id)
	{
		$len = 0;
		$len += $this->appendUINT32($personage_id);
		$this->insertHeader(304, $len);
	}

	private function appendSetQuiet($personage_id, $timeout)
	{
		$len = 0;
		$len += $this->appendUINT32($personage_id);
		$len += $this->appendUINT32($timeout);
		$this->insertHeader(303, $len);
	}

	
	public function appendSendMessage($channelId, $toID, $sMessage)
	{
		$len = 0;

		$len += $this->appendUINT16($channelId);
		if($toID)
		{
			$len += $this->appendUINT16(1);
			$len += $this->appendUINT32($toID);
		}
		else
		{
			$len += $this->appendUINT16(0);
		}
		$len += $this->appendUINT16(0);
		$len += $this->appendString($sMessage);
		$this->insertHeader(30, $len);

		return $m_Buffer;
	}

	private function encodeHeader(&$sync, &$id, &$length)
	{		
		if(rand(0, 1))
		{
			$sync |= 0x80;
		}
		else
		{
			$id |= 0x8000;
		}
		if(rand(0, 1))
		{
			$sync |= 0x20;
		}
		else
		{	
			$length |= 0x40000000;
		}
		if(rand(0, 1))
		{
			$sync |= 0x08;
		}
		else
		{	
			$length |= 0x80000000;
		}
	}

	private function insertHeader($id, $len)
	{	
		$sync = 0x57;
		$this->encodeHeader($sync, $id, $len);
		$this->insertUINT32($len);
		$this->insertUINT16($id);
		$this->insertUINT8($sync);
	}
	private function encodeCommand()
	{
	}
	
	private function decodeCommand()
	{
	}
}
?>
